package com.cennavi.minemapdemo.util;

import com.minedata.minemap.geometry.LatLng;

/**矩形类
 * Created by lijingru on 2017/4/26.
 */

public class GeoRect {
    LatLng pointLB;
    LatLng pointRT;


    public GeoRect() {
        this.pointLB = new LatLng(0, 0);
        this.pointRT = new LatLng(0, 0);
    }

    public GeoRect(LatLng pointLB, LatLng pointRT) {
        if(pointLB != null && pointRT != null) {
            this.pointLB = pointLB;
            this.pointRT = pointRT;
        } else {
            this.pointLB = new LatLng(0, 0);
            this.pointRT = new LatLng(0, 0);
        }

    }

    public GeoRect(double left, double top, double right, double bottom) {
        this.pointLB = new LatLng(bottom, left);
        this.pointRT = new LatLng(top, right);
    }

    public GeoRect(GeoRect rect) {
        if(rect == null) {
            this.pointLB = new LatLng(0, 0);
            this.pointRT = new LatLng(0, 0);
        } else {
            this.pointLB = new LatLng(rect.pointLB);
            this.pointRT = new LatLng(rect.pointRT);
        }

    }
    public LatLng getPointLB() {
        return this.pointLB;
    }

    public void setPointLB(LatLng pointLB) {
        this.pointLB = pointLB;
    }

    public LatLng getPointRT() {
        return this.pointRT;
    }

    public void setPointRT(LatLng pointRT) {
        this.pointRT = pointRT;
    }

    public double getLeft() {
        return this.pointLB.getLongitude();
    }

    public double getRight() {
        return this.pointRT.getLongitude();
    }

    public double getTop() {
        return this.pointRT.getLatitude();
    }

    public double getBottom() {
        return this.pointLB.getLatitude();
    }

    public void setLeft(float left) {
        this.pointLB.setLongitude(left);
    }

    public void setRight(float right) {
        this.pointRT.setLongitude(right);
    }

    public void setTop(float top) {
        this.pointRT.setLatitude(top);
    }

    public void setBottom(float bottom) {
        this.pointLB.setLatitude(bottom);
    }

    public boolean isIntersect(GeoRect rect) {
        return Math.min(this.pointLB.getLongitude(), this.pointRT.getLongitude())
                <= Math.max(rect.pointLB.getLongitude(), rect.pointRT.getLongitude())
                && Math.min(rect.pointLB.getLongitude(), rect.pointRT.getLongitude())
                <= Math.max(this.pointLB.getLongitude(), this.pointRT.getLongitude())
                && Math.min(this.pointLB.getLatitude(), this.pointRT.getLatitude())
                <= Math.max(rect.pointLB.getLatitude(), rect.pointRT.getLatitude())
                && Math.min(rect.pointLB.getLatitude(), rect.pointRT.getLatitude())
                <= Math.max(this.pointLB.getLatitude(), this.pointRT.getLatitude());
    }

    public String toString() {
        return new String("LB:" + this.pointLB.getLongitude() + "," + this.pointLB.getLatitude()
                + "RT:" + this.pointRT.getLongitude() + "," + this.pointRT.getLatitude());
    }


    public boolean contains(GeoRect another) {
        return this.pointLB.getLongitude() <= another.pointLB.getLongitude()
                && this.pointRT.getLongitude() >= another.pointRT.getLongitude()
                && this.pointLB.getLatitude() <= another.pointLB.getLatitude()
                && this.pointRT.getLatitude() >= another.pointRT.getLatitude();
    }

    public boolean contains(int x, int y) {
        return this.pointLB.getLongitude() <= x && this.pointRT.getLongitude() >= x
                && this.pointLB.getLatitude() <= y && this.pointRT.getLatitude() >= y;
    }

    public boolean intersect(GeoRect another) {
        return this.intersect(another.pointLB.getLongitude(), another.pointRT.getLatitude()
                , another.pointRT.getLongitude(), another.pointLB.getLatitude());
    }

    public boolean intersect(double left, double top, double right, double bottom) {
        if(this.intersects(left, top, right, bottom)) {
            if(this.pointLB.getLongitude() < left) {
                this.pointLB.setLongitude(left);
            }

            if(this.pointRT.getLatitude() > top) {
                this.pointRT.setLatitude(top);
            }

            if(this.pointRT.getLongitude() > right) {
                this.pointRT.setLongitude(right);
            }

            if(this.pointLB.getLatitude() < bottom) {
                this.pointLB.setLatitude(bottom);
            }

            return true;
        } else {
            return false;
        }
    }

    public boolean intersects(double left, double top, double right, double bottom) {
        return this.pointLB.getLongitude() < right
                && left < this.pointRT.getLongitude()
                && this.pointRT.getLatitude() > bottom
                && top > this.pointLB.getLatitude();
    }

    public static boolean intersects(GeoRect a, GeoRect b) {
        return a.pointLB.getLongitude() < b.pointRT.getLongitude()
                && b.pointLB.getLongitude() < a.pointRT.getLongitude()
                && a.pointRT.getLatitude() > b.pointLB.getLatitude()
                && b.pointRT.getLatitude() > a.pointLB.getLatitude();
    }

    public void extend(GeoRect another) {
        if(another != null) {
            if(this.pointLB.getLongitude() > another.pointLB.getLongitude()) {
                this.pointLB.setLongitude(another.pointLB.getLongitude());
            }

            if(this.pointRT.getLongitude() < another.pointRT.getLongitude()) {
                this.pointRT.setLongitude(another.pointRT.getLongitude());
            }

            if(this.pointLB.getLatitude() > another.pointLB.getLatitude()) {
                this.pointLB.setLatitude(another.pointLB.getLatitude());
            }

            if(this.pointRT.getLatitude() < another.pointRT.getLatitude()) {
                this.pointRT.setLatitude(another.pointRT.getLatitude());
            }
        }

    }

    public void extend(LatLng point) {
        if(point != null) {
            if(this.pointLB.getLongitude() > point.getLongitude()) {
                this.pointLB.setLongitude(point.getLongitude());
            }

            if(this.pointRT.getLongitude() < point.getLongitude()) {
                this.pointRT.setLongitude(point.getLongitude());
            }

            if(this.pointLB.getLatitude() > point.getLatitude()) {
                this.pointLB.setLatitude(point.getLatitude());
            }

            if(this.pointRT.getLatitude() < point.getLatitude()) {
                this.pointRT.setLatitude(point.getLatitude());
            }
        }

    }

    public boolean isEmpty() {
        return this.pointLB.getLongitude() >= this.pointRT.getLongitude() || this.pointLB.getLatitude() >= this.pointRT.getLatitude();
    }

    public double width() {
        return this.pointRT.getLongitude() - this.pointLB.getLongitude();
    }

    public double height() {
        return this.pointRT.getLatitude() - this.pointLB.getLatitude();
    }

    public double centerX() {
        return (this.pointLB.getLongitude() + this.pointRT.getLongitude())/2;
    }

    public double centerY() {
        return (this.pointLB.getLatitude() + this.pointRT.getLatitude())/2;
    }

    public LatLng center() {
        return new LatLng(this.centerY(), this.centerX());
    }

    public boolean equals(Object o) {
        if(o != null && o instanceof GeoRect) {
            GeoRect another = (GeoRect)o;
            if(this.pointLB.equals(another.pointLB) && this.pointRT.equals(another.pointRT)) {
                return true;
            }
        }

        return false;
    }
}
